﻿using Furion;
using Furion.DependencyInjection;
using Furion.FriendlyException;
using Microsoft.Extensions.Caching.Distributed;
using System;
using System.Threading;
using System.Threading.Tasks;
using YFurion.Localization;
using YFurion.Localization.Extensions;
using YFurion.Session;

namespace YFurion.Application
{
    public abstract class ServiceBase : IScoped
    {
        protected IYSession YSession { get; }

        protected ILocalizationManager LocalizationManager { get; }

        protected IDistributedCache DistributedCache { get; }

        /// <summary>
        /// 数据不存在
        /// </summary>
        protected string DataDoesNotExist { get; set; }

        protected ServiceBase()
        {
            YSession = App.GetService<IYSession>();
            LocalizationManager = App.GetService<ILocalizationManager>();
            DistributedCache = App.GetService<IDistributedCache>();
            DataDoesNotExist = LocalizationManager.GetCurrentString("该数据不存在或已被删除");
        }

        /// <summary>
        /// 在调用方法之前调用
        /// </summary>
        /// <typeparam name="TEntity"></typeparam>
        /// <param name="entity"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        protected async Task OnExecuting<TEntity>(TEntity entity, CancellationToken cancellationToken)
        {
            if (entity == null)
            {
                throw Oh(DataDoesNotExist);
            }
            await Task.CompletedTask;
        }

        /// <summary>
        /// 异步设置缓存
        /// </summary>
        /// <typeparam name="TValue"></typeparam>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <param name="options"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        protected async Task SetCacheAsync<TValue>(string key, TValue value, CancellationToken cancellationToken, DistributedCacheEntryOptions options = null)
        {
            if (options == null)
            {
                await DistributedCache.SetAsync(key, value, cancellationToken);
            }
            else
            {
                await DistributedCache.SetAsync(key, value, options, cancellationToken);
            }
        }

        /// <summary>
        /// 异步获取缓存
        /// </summary>
        /// <typeparam name="TValue"></typeparam>
        /// <param name="key"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        protected async Task<TValue> GetCacheAsync<TValue>(string key, CancellationToken cancellationToken)
        {
            TValue value = await DistributedCache.GetAsync<TValue>(key, cancellationToken);
            return value;
        }

        /// <summary>
        /// 异步获取或创建缓存
        /// </summary>
        /// <typeparam name="TValue"></typeparam>
        /// <param name="key"></param>
        /// <param name="func"></param>
        /// <param name="cancellationToken"></param>
        /// <param name="options"></param>
        /// <returns></returns>
        protected async Task<TValue> GetOrCreateCacheAsync<TValue>(string key, Func<CancellationToken, Task<TValue>> func, CancellationToken cancellationToken, DistributedCacheEntryOptions options = null)
        {
            TValue value;
            if (options == null)
            {
                value = await DistributedCache.GetOrCreateAsync(key, func, cancellationToken);
            }
            else
            {
                value = await DistributedCache.GetOrCreateAsync(key, func, options, cancellationToken);
            }
            return value;
        }

        /// <summary>
        /// 异步移除缓存
        /// </summary>
        /// <param name="key"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        protected async Task RemoveCacheAsync(string key, CancellationToken cancellationToken)
        {
            await DistributedCache.RemoveAsync(key, cancellationToken);
        }

        /// <summary>
        /// 抛出字符串异常
        /// </summary>
        /// <param name="errorMessage">异常消息</param>
        /// <param name="args">String.Format 参数</param>
        /// <returns>异常实例</returns>
        protected Exception Oh(string errorMessage, params object[] args)
        {
            return Oops.Oh(errorMessage, args);
        }

        /// <summary>
        /// 是否正确年份
        /// </summary>
        /// <param name="year"></param>
        /// <param name="maxSubValue"></param>
        /// <returns></returns>
        protected bool IsRightYear(int year, int maxSubValue = 3)
        {
            int sub = DateTime.Now.Year - year;
            return sub > 0 && sub < maxSubValue;
        }
    }
}
